<?php
/*
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/**
 * AppleTV <--> flickr proxy script
 *
 * Use this script to get private photos from your flickr stream and sets.
 * Also, you can make flickr api calls via AppleTV flickr search. Read ALL 
 * the comments before trying to install.
 *
 * To make this work with apple tv follow these steps:
 *
 *    1. Change AppleTV /etc/hosts so api.flickr.com points to a php enabled server
 *    2. Install this script as index.php on the php enabled server under /services/rest
 *    3. Get a flickr api auth_token
 *    4. Set Application Parameters $flickr_key, $flickr_secret, $user_id, and $auth_token 
 *
 * You can get an auth_token by creating a frob then pasting a similiar url into a browser:
 *
 *     http://api.flickr.com/services/rest/?
 *         api_key=2fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&
 *         frob=7215xxxxxxxxxxxxx-xxxxxx53919396f-831xxx&
 *         method=flickr.auth.getToken&
 *         user_id=3562xxxxxxxx&api_sig=bab5xxxxxxxxx4794xxxxxxxxxxxx
 *
 */

// Set Application Parameters: 
$flickr_key    = '********************************';   /* This is your API Key    */
$flickr_secret = '****************';                   /* This is your API Secret */ 
$user_id       = '********@***';                       /* This is your NSID       */
$auth_token    = '*****************-****************'; /* This is complicated     */

// Grab includes from http://code.google.com/p/spaph/source/browse/#svn/trunk/app/lib/HTTP
// Put HTTP in same directory as this script so they can be included here!
include('HTTP/Response.php');
include('HTTP/Request.php');

//error_log(var_export($_REQUEST,true)); // <-- troubleshooting

// Get a curl wrapper. Make sure php curl extension is available.
// http://www.php.net/manual/en/book.curl.php
$agent = new HTTP_Request();

// Find the flickr api method in the query string
$method = isset($_REQUEST['method']) ? $_REQUEST['method'] : '';

// Follow the if, else if logic...

if( preg_match('/flickr.people.(getInfo|findByUsername)/',$method) ) {
    // AppleTv is doing some investigation
    $url = get_url(false, array('api_key'=>$flickr_key));
}
else if( preg_match('/flickr.photos.search/',$method) && preg_match('/method=/', $_REQUEST['text'])) {
    /* 
       Make flickr api calls via AppleTV search box. Use semicolons to separate query parameters.
       So, in the search box there might be something starting with method=. Here are a few examples
       to try in the AppleTV search box:
      
       "method=flickr.interestingness.getList"
       "method=flickr.favorites.getList;user_id=35629729@N00"
    */
    $args = array(
        'method'=>'flickr.photos.search',
        'auth_token'=>$auth_token,
        'per_page'=>500,
        'api_key'=>$flickr_key);

    foreach(explode(';',$_REQUEST['text']) as $keyval) {
        list($key, $val) = explode('=',$keyval);
        $args[$key] = $val;
    }

    // Don't need this now.
    unset($_REQUEST['text']);

    $url = get_url($flickr_secret,$args);
}
else if( preg_match('/flickr.people.getPublicPhotos/',$method) ) {
    // AppleTV wants public but we want private ones too
    $url = get_url($flickr_secret, array(
        'method'=>'flickr.photos.search',
        'auth_token'=>$auth_token,
        'api_key'=>$flickr_key));
}
else if( preg_match('/flickr.photosets.getList/',$method) ) {
    // AppleTV getting photosets
    $url = get_url($flickr_secret, array(
        'method'=>'flickr.photosets.getList',
        'auth_token'=>$auth_token,
        'api_key'=>$flickr_key));
}
else if( preg_match('/flickr.photosets.getPhotos/',$method) ) {
    // AppleTV getting photos
    $url = get_url($flickr_secret, array(
        'method'=>'flickr.photosets.getPhotos',
        'auth_token'=>$auth_token,
        'api_key'=>$flickr_key));
}
else if( preg_match('/flickr.photos.getSizes/',$method) ) {
    // AppleTV getting photo sizes
    $url = get_url($flickr_secret, array(
        'method'=>'flickr.photos.getSizes',
        'auth_token'=>$auth_token,
        'api_key'=>$flickr_key));
}
else if( preg_match('/flickr.contacts.getPublicList/',$method) ) {
    // AppleTV wants contacts' public list but we want more!
    // So, sign with auth_token.
    $url = get_url($flickr_secret, array(
        'method'=>'flickr.contacts.getList',
        'auth_token'=>$auth_token,
        'api_key'=>$flickr_key));
}
else if( preg_match('/flickr.photos.search/',$method) ) {
    // Plain search via AppleTV search box. Nothing special here.
    $url = get_url(false, array('api_key'=>$flickr_key));
}
else {
    // Oops, I wonder what happened. Check the error log. 
    error_log('no flickr proxy');
    error_log(var_export($_REQUEST,true));
    exit;
}

//error_log($url); // <-- troubleshooting

// Call flickr api
$response = $agent->get($url);

//error_log($response->code . ' ' . $url); // <-- troubleshooting

// Send content back to AppleTV
print header('content-type: text/xml; charset=utf-8');
print $response->data;
exit;

/**
 * Create a suitable url for flickr api
 *
 * @param string $flickr_secret
 * @param array  $query_parts
 * @return string
 */
function get_url($flickr_secret, $query_parts=array()) {
    $query_signed = array();
    $signature_str = '';
    $signature_md5 = '';

    foreach($_REQUEST as $key => $val) {
        if(!isset($query_parts[$key])) {
            $query_parts[$key] = $val;
        }
    }

    ksort($query_parts);
    foreach($query_parts as $key => $val) {
        $signature_str .= $key.$val; 
    }

    if($flickr_secret) {
        $hash_me = $flickr_secret.$signature_str;
        $signature_md5 = md5($hash_me);
        $query_parts['api_sig'] = $signature_md5;
    }

    foreach($query_parts as $key => $val) {
        $query_signed[] = $key .'='. $val;
    }

    $url = 'http://api.flickr.com/services/rest/?'.implode('&',$query_signed);

    return $url;
}
?>
